<template>
  <div class="materials-page">
    <div class="button-groups">
      <el-button type="primary" @click="getArticleContent">
        提交文章内容
      </el-button>
    </div>
    <el-input v-model="title" placeholder="请输入文章标题" />
    <div style="border: 1px solid #ccc;margin-top: 10px;">
      <div id="toolbar-container" style="border-bottom: 1px solid #ccc">
        <!-- 工具栏 -->
      </div>
      <div id="editor-container" style="height: 600px; overflow-y: hidden;">
        <!-- 编辑器 -->
      </div>
    </div>

    <!-- 模板 -->
    <el-dialog
      title="模板"
      :visible.sync="templateModalVisible"
      width="60%"
      top="30vh"
    >
      <div class="template-content">
        <div class="left-sidebar">
          <div
            class="side-item"
            v-for="(item, index) in templates"
            :class="{ active: highlightIndex === index }"
            :key="index"
            @click="checkoutHighlightIndex(index)"
          >
            {{ item.title }}
          </div>
        </div>
        <div class="right-content" v-html="articleContent"></div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="templateModalVisible = false">取 消</el-button>
        <el-button type="primary" @click="handleConfirm">
          确 定
        </el-button>
      </span>
    </el-dialog>
    <MapSelect ref="ms" @on-select="selectAddress" />
  </div>
</template>

<script>
import { createEditor, createToolbar, Boot } from "@wangeditor/editor";
import { TemplateMenu } from "./TemplateMenu";
import { MapMenu } from "./MapMenu";
import { getToken } from "@/utils/auth";

import { fetchTemplates, addArticle, uploadImage } from "@/api/editor";

import MapSelect from "./components/MapSelect.vue";

export default {
  components: { MapSelect },
  data() {
    return {
      title: "",
      editor: null,
      toolbarConfig: {
        mode: "default",
        excludeKeys: ["blockquote", "codeBlock", "emotion", "insertTable"],
        insertKeys: {
          index: 5, // 插入的位置，基于当前的 toolbarKeys
          keys: ["template", "map"]
        }
      },
      highlightIndex: 0,
      articleContent: "",
      templates: [],
      templateModalVisible: false,
      form: {
        signAddress: "",
        coordinateX: "",
        coordinateY: ""
      }
    };
  },
  created() {
    // 获取模板
    this.getTemplates();
  },
  mounted() {
    let editor = createEditor({
      selector: "#editor-container",
      config: {
        MENU_CONF: {
          uploadImage: {
            server: "/dev-api/system/ossFile/upload",
            fieldName: "file",
            headers: {
              Authorization: "Bearer " + getToken()
            },
            customInsert(res, insertFn) {
              insertFn(res?.data, "", "");
            }
          }
        }
      }
    });

    if (!editor.getAllMenuKeys()?.includes("template")) {
      Boot.registerMenu({
        key: "template", // 定义 menu key ：要保证唯一、不重复（重要）
        factory() {
          return new TemplateMenu();
        }
      });
    }

    if (!editor.getAllMenuKeys()?.includes("map")) {
      Boot.registerMenu({
        key: "map", // 定义 menu key ：要保证唯一、不重复（重要）
        factory() {
          return new MapMenu();
        }
      });
    }

    editor["showTemplateModal"] = () => {
      this.templateModalVisible = true;
    };

    // 自定义函数，用来展示插入变量弹框
    editor["showMapModal"] = () => {
      this.$refs.ms.show();
      this.$refs.ms.setLocationByLatLng(
        this.form.coordinateX,
        this.form.coordinateY
      );
    };

    createToolbar({
      editor: editor,
      selector: "#toolbar-container",
      config: this.toolbarConfig
    });

    window.commonEditor = editor;
  },
  beforeDestroy() {
    const editor = window.commonEditor;
    if (editor == null) return;
    editor.destroy(); // 组件销毁时，及时销毁编辑器
  },
  methods: {
    // 获取模板
    async getTemplates() {
      try {
        const result = await fetchTemplates({ pageNum: 1, pageSize: 10 });
        this.templates = result?.rows;
        this.articleContent = this.templates[this.highlightIndex].content;
      } catch (error) {
        console.log(error);
      }
    },
    handleConfirm() {
      const editor = window.commonEditor;

      editor.focus();

      // 获取带有 HTML 标签的字符串
      const htmlContent = this.articleContent;

      // 使用 dangerouslyInsertHtml 方法插入带有 HTML 标签的内容
      editor.dangerouslyInsertHtml(htmlContent);

      // 关闭模态框
      this.templateModalVisible = false;
    },
    checkoutHighlightIndex(index) {
      this.highlightIndex = index;
      this.articleContent = this.templates[index].content;
    },
    // 地址选择后的回调函数
    selectAddress(address, lat, lng) {
      this.form.signAddress = address;
      this.form.coordinateX = lat;
      this.form.coordinateY = lng;

      const editor = window.commonEditor;

      editor.focus();

      // 转成图片放入富文本
      this.screenshot();
    },
    screenshot() {
      const node = document.getElementById("mapContainer");

      domtoimage
        .toPng(node)
        .then(dataUrl => {
          this.uploadImage(dataUrl);
        })
        .catch(error => {
          console.error("domtoimage 出现问题! ", error);
        });
    },

    base64StringToFile(base64String, fileName) {
      try {
        const byteCharacters = atob(base64String);
        const byteArray = new Uint8Array(byteCharacters.length);

        for (let i = 0; i < byteCharacters.length; i++) {
          byteArray[i] = byteCharacters.charCodeAt(i);
        }

        const blob = new Blob([byteArray], {
          type: "application/octet-stream"
        });
        const file = new File([blob], fileName, {
          type: "application/octet-stream"
        });

        return file;
      } catch (error) {
        console.error("base64StringToFile 出现问题! ", error);
        return null;
      }
    },
    async uploadImage(dataUrl) {
      const file = this.base64StringToFile(
        dataUrl.substring(dataUrl.indexOf(",") + 1),
        "1.png"
      );

      const editor = window.commonEditor;
      try {
        const formData = new FormData();
        formData.append("file", file);
        let result = await uploadImage(formData);
        const image = `<img src="${result?.data}"/>`;
        editor.dangerouslyInsertHtml(image);
        this.$refs.ms.close();
      } catch (error) {
        console.log(error);
      }
    },
    // 新增文章
    async getArticleContent() {
      if (!this.title) {
        return this.$message.warning("请输入文章标题");
      }

      const editor = window.commonEditor;
      const content = editor.getHtml();

      console.log(content);
      try {
        const result = await addArticle({ title: this.title, content });
        if (result.code === 200) {
          this.$message.success("新增文章成功");
          this.title = "";
          editor.setHtml("");
        }
      } catch (error) {
        console.log(error);
      }
    }
  }
};
</script>

<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="scss" scoped>
.materials-page {
  padding: 20px;
  .button-groups {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 12px;
  }
}
</style>
<style lang="scss">
.template-content {
  display: flex;
  justify-content: space-between;
  padding: 0 40px;
  .left-sidebar {
    display: flex;
    flex-direction: column;
    align-items: center;
    height: 400px;
    overflow-y: auto;
    .side-item {
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 10px 20px;
      border: solid 1px #999999;
      border-radius: 6px;
      box-sizing: border-box;
      width: 120px;
      line-height: 1.3;
      cursor: pointer;
      & + .side-item {
        margin-top: 10px;
      }
      &.active {
        background: #3471ff;
        border-color: #3471ff;
        color: #ffffff;
      }
    }
  }
  .right-content {
    flex: 1;
    margin-left: 20px;
    border: solid 1px #999999;
    border-radius: 6px;
    height: 400px;
    overflow-y: auto;
    box-sizing: border-box;
    padding: 10px;
  }
}
</style>
